home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / daemons / mopd / RCS / mopd.c,v < prev   
Encoding:
Text File  |  1992-08-11  |  12.7 KB  |  600 lines

  1. head     1.5;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    shirriff:1.5; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.5
  10. date     92.07.21.22.04.56;  author shirriff;  state Exp;
  11. branches ;
  12. next     1.4;
  13.  
  14. 1.4
  15. date     92.06.16.21.15.37;  author jhh;  state Exp;
  16. branches ;
  17. next     1.3;
  18.  
  19. 1.3
  20. date     92.06.16.20.56.33;  author shirriff;  state Exp;
  21. branches ;
  22. next     1.2;
  23.  
  24. 1.2
  25. date     92.05.28.23.24.55;  author shirriff;  state Exp;
  26. branches ;
  27. next     1.1;
  28.  
  29. 1.1
  30. date     91.12.18.13.45.18;  author shirriff;  state Exp;
  31. branches ;
  32. next     ;
  33.  
  34.  
  35. desc
  36. @@
  37.  
  38.  
  39. 1.5
  40. log
  41. @Added check so mopd won't respond to a non-sprite machine.
  42. Added more debugging information.
  43. Changed handling of out-of-sequence packets so they get dropped on the
  44. floor.  Attempting to respond to out-of-sequence packets caused the
  45. server to fall behind, so it was responding to the wrong packet and never
  46. got back in sync.
  47. @
  48. text
  49. @/*
  50.  * MOP server daemon.
  51.  */
  52.  
  53. #include <stdio.h>
  54. #include <sys/file.h>
  55. #include <sys/types.h>
  56. #include <sys/socket.h>
  57. #include <net/if_arp.h>
  58. #include <netinet/if_ether.h>
  59. #include <netEther.h>
  60. #ifndef mip
  61. #define mips 1
  62. #define notreallymips
  63. #endif
  64. #ifndef LANGUAGE_C
  65. #define LANGUAGE_C
  66. #endif
  67. #ifndef MIPSEL
  68. #define MIPSEL
  69. #endif
  70. #include <ds3100.md/sys/exec.h>
  71. #ifdef notreallymips
  72. #undef mips
  73. #endif
  74. #include <host.h>
  75. #include <mopd.h>
  76. #include <signal.h>
  77. #include <varargs.h>
  78. #include <time.h>
  79. #include <string.h>
  80.  
  81. Net_EtherAddress myAddr;
  82. Net_EtherAddress multiAddr;
  83.  
  84. unsigned char broadcast[] = MOP_BROADCAST;
  85.  
  86. int debug = 0;        /* Flag for debug mode. */
  87.  
  88. extern int errno;
  89.  
  90. #define WAITING 0
  91. #define SENDING 1
  92. #define DONE    2
  93.  
  94. int mode=WAITING;    /* The state we're in. */
  95. int seq, seqHi;        /* The current sequence number. */
  96. int bootFd;        /* The boot program fd. */
  97. int mopFd;        /* The mop device fd. */
  98. u_char client[6];    /* The client we're dealing with. */
  99. int loadAddr, length, startAddr, fileOffset; /* Boot file parameters. */
  100. char filename[100];
  101.  
  102. static void log();
  103. int timer();
  104.  
  105. #if 0
  106. static char    *mopdlog = "/sprite/admin/mopdlog";
  107. static char    *openFlags = "a+";
  108. #else
  109. static char    *mopdlog = "/dev/syslog";
  110. static char    *openFlags = "w";
  111. #endif
  112.  
  113. void
  114. main(argc,argv)
  115.     int argc;
  116.     char **argv;
  117. {
  118.     unsigned char buf[BUF_LEN];
  119.     int len;
  120.     u_char us[6], them[6];
  121.     char myName[50];
  122.     mopHdr *mopHdrPtr = (mopHdr *)buf;
  123.     Host_Entry *myEntry, *theirEntry;
  124.     Net_Address theirNetAddress;
  125.     int        i;
  126.  
  127.     multiAddr = * (Net_EtherAddress *) broadcast;
  128.     if (gethostname(myName,50)<0) {
  129.     perror("gethostname");
  130.     exit(-1);
  131.     }
  132.     myEntry = Host_ByName(myName);
  133.     if (myEntry == NULL) {
  134.     perror("Host_ByName");
  135.     exit(-1);
  136.     }
  137.     for (i = 0; i < myEntry->numNets; i++) {
  138.     if (myEntry->nets[i].netAddr.type == NET_ADDRESS_ETHER) {
  139.         (void) Net_GetAddress(&myEntry->nets[i].netAddr,
  140.             (Address) &myAddr);
  141.         break;
  142.     }
  143.     }
  144.     Host_End();
  145.     for (argc--, argv++ ; argc > 0 ; argc--, argv++) {
  146.     if (argv[0][0] == '-') {
  147.         switch (argv[0][1]) {
  148.         case 'd':
  149.             debug++;
  150.             break;
  151.         }
  152.         }
  153.     }
  154.  
  155.     if (debug==0) {
  156.     if (fork()) exit(0);
  157.     }
  158.  
  159.     signal(SIGALRM, timer);
  160.  
  161.     mopFd = open(MOP_DEVICE, O_RDWR, 0);
  162.     if (mopFd < 0) {
  163.     perror(MOP_DEVICE);
  164.     exit(-1);
  165.     }
  166.  
  167.     log("Mop server %s starting", myName);
  168.  
  169. #define US mopHdrPtr->header.ether_dhost
  170. #define THEM mopHdrPtr->header.ether_shost
  171.     while (1) {
  172.     len = read(mopFd, buf, 1000);
  173.  
  174.     if (debug>1) {
  175.         log("Packet from %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x to %2.2x:%2.2x:%2.2x:%2.2x.", THEM[0],THEM[1],THEM[2],THEM[3],THEM[4],THEM[5], US[0],
  176.             US[1], US[2],US[3],US[4],US[5]);
  177.     }
  178.  
  179.     if (!bcmp(&multiAddr, US, sizeof(Net_EtherAddress))) {
  180.         if (debug) {
  181.         log("Got a broadcast packet");
  182.         }
  183.         Host_Start();
  184.         theirNetAddress.type = NET_ADDRESS_ETHER;
  185.         bcopy(THEM,&theirNetAddress.address.ether,
  186.             sizeof(Net_EtherAddress));
  187.         theirEntry = Host_ByNetAddr(&theirNetAddress);
  188.         Host_End();
  189.         if (theirEntry == NULL) {
  190.         log("Packet from unknown %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
  191.             THEM[0],THEM[1],THEM[2],THEM[3],THEM[4],THEM[5]);
  192.         continue;
  193.         }
  194.     } else if (bcmp(&myAddr, US, sizeof(Net_EtherAddress))) {
  195.         log("Mystery packet to %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
  196.             US[0],US[1],US[2],US[3],US[4],US[5]);
  197.         continue;
  198.     }
  199.  
  200.     if (debug>2) {
  201.         log("Received: %d", mopHdrPtr->code);
  202.     }
  203.  
  204.     if (mode == WAITING) {
  205.         bcopy(THEM,client,6);
  206.     } else if (bcmp(client, THEM,6)!=0) {
  207.         /*
  208.          * We can't handle two clients at once, so this one must wait.
  209.          */
  210.         if (debug) {
  211.         log("Mop request collision");
  212.         }
  213.         continue;
  214.     }
  215.      
  216.     if (mopHdrPtr->code == MOP_REQ) {
  217.         if (initRequest(buf)<0) continue;
  218.     }
  219.     if (mode==SENDING && (mopHdrPtr->code == MOP_REQ_LOAD ||
  220.         mopHdrPtr->code == MOP_REQ)) {
  221.         alarm(5);
  222.         sendData(buf);
  223.     } else if (mode==DONE && mopHdrPtr->code == MOP_REQ_LOAD) {
  224.         if (debug) {
  225.         mopReqLoad *mopReqLoadPtr = (mopReqLoad *)(buf+HDR_LEN);
  226.         log("Load completed: status %d", mopReqLoadPtr->error);
  227.         }
  228.         alarm(0);
  229.         close(bootFd);
  230.         mode = WAITING;
  231.     } else {
  232.         log("Out of order function: %d", mopHdrPtr->code);
  233.         if (mode==1) {
  234.         close(bootFd);
  235.         }
  236.         mode = WAITING;
  237.     }
  238.     }
  239. }
  240.  
  241. /*
  242.  * Transmit a packet.
  243.  */
  244. mopXmit(fd, src, dst, len, code, buf)
  245.     int fd;
  246.     u_char *src;
  247.     u_char *dst;
  248.     int    len;
  249.     int code;
  250.     char *buf;
  251. {
  252.     short shortVal;
  253.     mopHdr *mopHdrPtr = (mopHdr *)buf;
  254.     if (debug>2) {
  255.     log("Transmitting: code %d, len: %d", code, len);
  256.     }
  257.     bcopy(src, mopHdrPtr->header.ether_shost, 6);
  258.     bcopy(dst, mopHdrPtr->header.ether_dhost, 6);
  259.     shortVal = SWAP2(NET_ETHER_MOP);
  260.     bcopy(&shortVal, &mopHdrPtr->header.ether_type, sizeof(short));
  261.     shortVal = len+1; /* One byte for the code */
  262.     bcopy(&shortVal, &mopHdrPtr->len, sizeof(short));
  263.     mopHdrPtr->code = code;
  264.     if (write(fd, buf, HDR_LEN+len)<0) {
  265.     log("MOP packet write error: %d", errno);
  266.     }
  267. }
  268.  
  269. /*
  270.  * Find how much code we should give the client.
  271.  */
  272. int
  273. findStart(inFd, fileOffset, loadAddr, progLen, startAddr)
  274. int inFd;            /* Fd for us to use */
  275. int *fileOffset;        /* Return: offset of program in file. */
  276. int *loadAddr;            /* Return: address to load program. */
  277. int *progLen;            /* Return: the length of the program. */
  278. int *startAddr;            /* Return: start of execution. */
  279. {
  280.     struct filehdr fileHdr;
  281.     struct aouthdr aoutHdr;
  282.  
  283.     read(inFd, &fileHdr, sizeof(struct filehdr));
  284.     read(inFd, &aoutHdr, sizeof(struct aouthdr));
  285.     aoutHdr.magic = UNSWAP2(aoutHdr.magic);
  286.     aoutHdr.vstamp = UNSWAP2(aoutHdr.vstamp);
  287.     aoutHdr.text_start = UNSWAP4(aoutHdr.text_start);
  288.     aoutHdr.tsize = UNSWAP4(aoutHdr.tsize);
  289.     aoutHdr.dsize = UNSWAP4(aoutHdr.dsize);
  290.     aoutHdr.entry = UNSWAP4(aoutHdr.entry);
  291.     fileHdr.f_magic = UNSWAP2(fileHdr.f_magic);
  292.     fileHdr.f_nscns = UNSWAP2(fileHdr.f_nscns);
  293.     if (fileHdr.f_magic != MIPSELMAGIC || aoutHdr.magic != OMAGIC) {
  294.     log("Bad magic number on boot file %s", filename);
  295.     log("f_magic = %x, want %x.  a_magic = %x, want %x",
  296.         fileHdr.f_magic, MIPSELMAGIC, aoutHdr.magic, OMAGIC);
  297.     }
  298.     *fileOffset = N_TXTOFF(fileHdr, aoutHdr);
  299.     *loadAddr = aoutHdr.text_start;
  300.     *progLen = aoutHdr.tsize+aoutHdr.dsize;
  301.     *startAddr = aoutHdr.entry;
  302.     if (debug) {
  303.     log("File: offset: %x, addr: %x, len: %x, start: %x\n", *fileOffset,
  304.         *loadAddr, *progLen, *startAddr);
  305.     }
  306. }
  307.  
  308. /*
  309.  * Open our input file.
  310.  */
  311. int
  312. openFile(mopPtr)
  313. mopReq *mopPtr;
  314. {
  315.     int bootFd;
  316.     char *machineType;
  317.     char *name;
  318.     char *strPtr;
  319.  
  320.     if (mopPtr->devType == 0x43) {
  321.     machineType = "ds3100.md";
  322.     } else if (mopPtr->devType == 0x5e) {
  323.     machineType = "ds5000.md";
  324.     } else {
  325.     log("Unknown machine type %d", mopPtr->devType);
  326.     return -1;
  327.     }
  328.     name = (mopPtr->softID != '\0') ? &mopPtr->softID : "sprite";
  329.     /*
  330.      * Drop any boot flags.
  331.      */
  332.     strPtr = strchr(name,' ');
  333.     if (strPtr != NULL) {
  334.     *strPtr = '\0';
  335.     }
  336.     sprintf(filename,"%s/%s/%s", BOOT_DIR, machineType, name);
  337.     bootFd = open(filename, O_RDONLY, 0);
  338.     if (debug) {
  339.     log("Booting %s", filename);
  340.     }
  341.     if (bootFd < 0) {
  342.     log("Couldn't open %s", filename);
  343.     /*
  344.      * See if we have an error file we can return.
  345.      */
  346.     sprintf(filename,"%s/%s/%s", BOOT_DIR, machineType, "err");
  347.     bootFd = open(filename, O_RDONLY, 0);
  348.     if (bootFd < 0) {
  349.         return -1;
  350.     }
  351.     }
  352.     return bootFd;
  353. }
  354.  
  355. /*
  356.  * log an error message
  357.  *
  358.  */
  359. static void
  360. log(va_alist)
  361.     va_dcl
  362. {
  363.         FILE *fp;
  364.         char *format;
  365.         va_list args;
  366.         time_t now;
  367.         char *t;
  368.  
  369.         va_start(args);
  370.         time(&now);
  371.         t = asctime(localtime(&now));
  372.         /* remove the newline */
  373.         t[24] = '\0';
  374.         if ((fp = fopen(mopdlog, openFlags)) == NULL) {
  375.         perror(mopdlog);
  376.         return;
  377.     }
  378.         fprintf(fp, "[mopd %s]: ", t);
  379.         format = va_arg(args, char *);
  380.         vfprintf(fp, format, args);
  381.         putc('\n', fp);
  382.         fclose(fp);
  383.         return;
  384. }
  385.  
  386. /*
  387.  * Handle an initial request.
  388.  */
  389. initRequest(buf)
  390.     char *buf;
  391. {
  392.     mopReq *mopPtr = (mopReq *)(buf+HDR_LEN);
  393.  
  394.     if (mode!=WAITING) {
  395.     if (debug) {
  396.         log("Wasn't expecting request");
  397.     }
  398.     }
  399.     seq = 0;
  400.     seqHi = 0;
  401.     bootFd = openFile(mopPtr);
  402.     if (bootFd<0) {
  403.     if (debug) {
  404.         log("openFile failed");
  405.     }
  406.     mode = WAITING;
  407.     return -1;
  408.     }
  409.     mode = SENDING;
  410.     if (findStart(bootFd, &fileOffset, &loadAddr, &length,
  411.         &startAddr)<0) {
  412.     if (debug) {
  413.         log("findStart failed");
  414.     }
  415.     mode = WAITING;
  416.     close(bootFd);
  417.     return -1;
  418.     }
  419.     return 0;
  420. }
  421.  
  422. /*
  423.  * Send the next data packet.
  424.  */
  425. sendData(buf)
  426. {
  427.     mopHdr *mopHdrPtr = (mopHdr *)buf;
  428.     mopLoad *mopLoadPtr = (mopLoad *)(buf+HDR_LEN);
  429.     mopReqLoad *mopReqLoadPtr = (mopReqLoad *)(buf+HDR_LEN);
  430.     mopParamLoad *mopParamLoadPtr = (mopParamLoad *)(buf+HDR_LEN);
  431.     int intVal;
  432.     int seqReq;
  433.     int curPos, toRead;
  434.     /*
  435.      * Check the sequence numbers.
  436.      */
  437.     if (mopHdrPtr->code == MOP_REQ) {
  438.     seqReq = 0;
  439.     } else {
  440.     seqReq = mopReqLoadPtr->loadNum;
  441.     if (debug) {
  442.         log("Requested sequence number %d\n", seqReq);
  443.     }
  444.     if (mopReqLoadPtr->error != 0) {
  445.         if (debug) {
  446.         log("Load error status %d", mopReqLoadPtr->error);
  447.         }
  448.         mode = WAITING;
  449.         close(bootFd);
  450.         return;
  451.     }
  452.     }
  453.     if (seqReq != seq) {
  454.     log("Out of sequence request %d vs %d from %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", seqReq, seq, THEM[0], THEM[1], THEM[2], THEM[3], THEM[4], THEM[5]);
  455.     /* Somehow we need to get back into sync. */
  456.     seq = seqReq;
  457.     return;
  458.     }
  459.     /*
  460.      * Transmit the data.
  461.      */
  462.     curPos = PACKET_SIZE*(seq+seqHi*256);
  463.     toRead = length-curPos;
  464.     if (toRead > PACKET_SIZE) {
  465.     toRead = PACKET_SIZE;
  466.     }
  467.     if (toRead > 0) {
  468.     lseek(bootFd, fileOffset+curPos, 0);
  469.     if (read(bootFd, buf+HDR_LEN+MOPLOAD_LEN, toRead) != toRead) {
  470.         log("Short boot file %s",filename);
  471.         mode = WAITING;
  472.         close(bootFd);
  473.         return;
  474.     }
  475.     mopLoadPtr->loadNum = seq;
  476.     intVal = UNSWAP4((loadAddr + curPos));
  477.     bcopy(&intVal, mopLoadPtr->loadAddr, sizeof(int));
  478.     toRead = PACKET_SIZE; /* HACK */
  479.     mopXmit(mopFd, &myAddr, client, MOPLOAD_LEN+toRead, MOP_LOAD, buf);
  480.     } else {
  481.     mopParamLoadPtr->loadNum = seq;
  482.     mopParamLoadPtr->parameters = 0;
  483.     intVal = UNSWAP4(startAddr);
  484.     if (debug) {
  485.         log("Transferring to %x", startAddr);
  486.     }
  487.     bcopy(&intVal, &mopParamLoadPtr->parameters+1, sizeof(int));
  488.     mopXmit(mopFd, &myAddr, client, sizeof(mopParamLoad)+sizeof(int),
  489.         MOP_PARAM_LOAD_XFER, buf);
  490.     mode = DONE;
  491.     }
  492.     seq++;
  493.     if (seq==256) {
  494.     seq=0;
  495.     seqHi++;
  496.     }
  497. }
  498.  
  499. /*
  500.  * Handle a timeout.
  501.  */
  502. timer()
  503. {
  504.     if (mode != WAITING) {
  505.     if (debug) {
  506.         log("Timeout");
  507.     }
  508.     close(bootFd);
  509.     mode = WAITING;
  510.     }
  511. }
  512. @
  513.  
  514.  
  515. 1.4
  516. log
  517. @port to new Host library
  518. now uses some of the standard Net stuff
  519. forgot to call Host_End
  520. @
  521. text
  522. @d75 2
  523. a76 1
  524.     Host_Entry *myEntry;
  525. d127 2
  526. a128 1
  527.         log("Packet from %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x to %2.2x:%2.2x:%2.2x:%2.2x.", THEM, US);
  528. d135 11
  529. d148 1
  530. a148 1
  531.             US);
  532. d393 3
  533. d398 1
  534. a398 1
  535.         log("Load error");
  536. d406 1
  537. a406 1
  538.     log("Out of sequence request %d vs %d from %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", seqReq, seq, THEM);
  539. d409 1
  540. @
  541.  
  542.  
  543. 1.3
  544. log
  545. @ken fixed a printf -- jhh
  546. @
  547. text
  548. @d33 2
  549. a34 2
  550. unsigned char myAddr[HOST_ETHER_ADDRESS_SIZE];
  551. unsigned char multiAddr[HOST_ETHER_ADDRESS_SIZE] = MOP_BROADCAST;
  552. d36 2
  553. d76 1
  554. d78 1
  555. d88 8
  556. a95 2
  557.     bcopy(myEntry->netAddr.etherAddr,myAddr, HOST_ETHER_ADDRESS_SIZE);
  558.  
  559. d129 1
  560. a129 1
  561.     if (!bcmp(multiAddr, US, HOST_ETHER_ADDRESS_SIZE)) {
  562. d133 1
  563. a133 1
  564.     } else if (bcmp(myAddr, US, HOST_ETHER_ADDRESS_SIZE)) {
  565. d414 1
  566. a414 1
  567.     mopXmit(mopFd, myAddr, client, MOPLOAD_LEN+toRead, MOP_LOAD, buf);
  568. d423 1
  569. a423 1
  570.     mopXmit(mopFd, myAddr, client, sizeof(mopParamLoad)+sizeof(int),
  571. @
  572.  
  573.  
  574. 1.2
  575. log
  576. @Increased timeout length, so mop doesn't time out on slow systems.
  577. Added feature to boot an error file if the file doesn't exist.
  578. (This file prints "file not found").
  579. @
  580. text
  581. @d307 1
  582. a307 1
  583.         fprintf(fp, "[%s]: ", t);
  584. d381 1
  585. @
  586.  
  587.  
  588. 1.1
  589. log
  590. @Initial revision
  591. @
  592. text
  593. @d150 1
  594. a150 1
  595.         alarm(2);
  596. d272 8
  597. a279 1
  598.     return -1;
  599. @
  600.